package com.swak.frame.support;

import java.util.List;
import java.util.ServiceLoader;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.lang.Nullable;
import com.google.common.collect.Lists;
import com.swak.frame.context.BoundContext;
import com.swak.frame.filter.ApiFilter;
import com.swak.frame.filter.adapter.ApiFilterChainFactoryAdapter;
import com.swak.frame.filter.adapter.FilterChainFactoryAdapter;

public class ServiceConfigurationSupport implements ApplicationContextAware {

    @Nullable
    private ConfigPipeline<ApiFilter> filterConfigPipeline;

    @Nullable
    private ApplicationContext applicationContext;

    protected void configureFilterHandler(ConfigPipeline<ApiFilter> filterPipeline) {}

    protected void extendconfigureFilters(ConfigPipeline<ApiFilter> filterPipeline) {}

    private final List<ApiFilter> getApiFilters() {
        if (this.filterConfigPipeline == null) {
            this.filterConfigPipeline = DefaultConfigPipeline.configPipeline();
            configureFilterHandler(this.filterConfigPipeline);
            if (this.filterConfigPipeline.isEmpty()) {
                addDefaultApiFilters(this.filterConfigPipeline);
            }
            extendconfigureFilters(this.filterConfigPipeline);
        }
        return this.filterConfigPipeline.pipelineList();
    }

    private final void addDefaultApiFilters(ConfigPipeline<ApiFilter> filterPipeline) {
        ServiceLoader<ApiFilter> filters = ServiceLoader.load(ApiFilter.class);
        filterPipeline.addLast(Lists.newArrayList(filters.iterator()));
    }

    @Bean("filterChainFactoryAdapter")
    @DependsOn("springBeanFactory")
    public FilterChainFactoryAdapter<BoundContext> filterChainFactoryAdapter() {
        return new ApiFilterChainFactoryAdapter(getApiFilters());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
